/************************************************************************

    PCem: IBM 5150 cassette support

    Copyright (C) 2019  John Elliott <seasip.webmaster@gmail.com>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*************************************************************************/

#ifndef _PZX_H_
#define _PZX_H_

typedef enum {
        PZX_CLOSED,  /* File is not open */
        PZX_IDLE,    /* File is open, no block loaded */
        PZX_IN_PULS, /* File is open, current block is a PULS block */
        PZX_IN_DATA, /* File is open, current block is a DATA block */
        PZX_IN_PAUS, /* File is open, current block is a PAUS block */
} PZX_STATE;

typedef struct pzxfile_t {
        FILE *input;            /* Input PZX file */
        uint8_t *curblock;      /* Currently-loaded block, if any */
        int level;              /* Current signal level */
        PZX_STATE state;        /* State machine current status */
                                /* State variables for PULS */
        uint32_t puls_ptr;      /* Pointer within PULS block */
        uint32_t puls_len;      /* Length of PULS block */
        uint32_t puls_count;    /* Count of pulses */
        uint32_t puls_duration; /* Duration of each pulse */
        uint32_t puls_remain;   /* Time remaining in this pulse */
                                /* State variables for PAUS */
        uint32_t paus_remain;   /* Time remaining in this pause */
                                /* State variables for DATA */
        uint32_t data_ptr;      /* Pointer within DATA block */
        uint32_t data_bits;     /* Count of bits */
        uint16_t data_tail;     /* Length of pulse after last bit */
        uint8_t data_mask;      /* Mask for current bit */
        uint8_t data_p0;        /* Length of 0 encoding */
        uint8_t data_p1;        /* Length of 1 encoding */
        int data_p;             /* Current sequence being emitted */
        uint32_t data_w;        /* Current waveform */
        uint32_t data_remain;   /* Current data pulse time remaining */
} pzxfile_t;

uint8_t *pzx_load_block(FILE *fp);

/* Initialise structure */
void pzx_init(pzxfile_t *pzx);

/* Open file for input */
const char *pzx_open(pzxfile_t *pzx, FILE *fp);

/* Close file */
void pzx_close(pzxfile_t *pzx);

/* Advance by 'time' samples (3.5MHz sample rate) and return current state */
int pzx_advance(pzxfile_t *pzx, int time);

#endif /* _PZX_H_ */
